package com.yuand.handler;

import com.alibaba.fastjson.JSONObject;
import com.yuand.channel.NettyChannel;
import com.yuand.utils.NettyUtil;
import com.yuand.utils.RedisService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * @author: yuand
 * @Description: < Netty的处理类 >
 */
@Component
@ChannelHandler.Sharable
@Slf4j
public class TcpServerHandler extends ChannelInboundHandlerAdapter {

	@Autowired
	private RedisService redisService;

	@Autowired
	private NettyChannel nettyChannel;

	/**
	 * 活跃的、有效的通道
	 * 第一次连接成功后进入的方法
	 * 客户端连接会触发
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		String channelId = ctx.channel().id().asLongText();
		String ip = NettyUtil.getRemoteAddress(ctx);
		if(!redisService.get("channelIp")){
			log.info("与通道号为" + channelId + "的客户端" + ip + "建立连接，通道开启！");
			//将tcp客户端的channel信息保存
			nettyChannel.addChannel(ctx.channel());
		}else{
			log.error("ip地址为" + ip + "的非法链接");
			ctx.disconnect();
		}
	}

	/**
	 * 不活动的通道
	 * 连接丢失后执行的方法（client端可据此实现断线重连）
	 *
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
		String channelId = ctx.channel().id().asLongText();
		//移除tcp客户端的channel信息
		nettyChannel.removeChannel(ctx.channel());
		//断开连接
		ctx.disconnect();
	}

	/**
	 * 拿到传过来的msg数据，开始处理
	 * 客户端发消息会触发
	 * @param ctx
	 * @param msg
	 * @throws Exception
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		//获取管道id
		String channelId = ctx.channel().id().asLongText();
		String ip = NettyUtil.getRemoteAddress(ctx);
		log.info("已进入read方法，开始处理数据......");
		ByteBuf bb = (ByteBuf) msg;
		String value = bb.toString(CharsetUtil.UTF_8);
		//打印客户端传递过来的值
		log.info("客户端发送的消息是......"+ value);
		
		//返回给客户端一个字符串
		ByteBuf result = Unpooled.copiedBuffer("我是服务端，没事别来烦我.........", CharsetUtil.UTF_8);
		ctx.writeAndFlush(result);

	}

	/**
	 * 服务端接收客户端发送过来的数据结束之后调用
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		super.channelReadComplete(ctx);
	}

	/**
	 * 异常处理
	 *
	 * @param ctx
	 * @param cause
	 * @throws Exception
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		super.exceptionCaught(ctx, cause);
		String channelId = ctx.channel().id().asLongText();
		log.error("通道号为" + channelId + "的客户端通道发生异常，数据无法解析：" + cause.getMessage());
	}

	/**
	 * 心跳机制，超时处理
	 *
	 * @param ctx
	 * @param evt
	 * @throws Exception
	 */
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		String channelId = ctx.channel().id().asLongText();
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent event = (IdleStateEvent) evt;
			String crewSim = "";
			if(redisService.hHasValue("crew_online", channelId)) {
				crewSim = redisService.hgetValue("crew_online", channelId).toString();
			}
			if (event.state() == IdleState.READER_IDLE) {
				log.error("通道号为" + channelId + "的客户端" + crewSim + "读超时，连接中断");
				ctx.disconnect();
			} else if (event.state() == IdleState.WRITER_IDLE) {
				log.error("通道号为" + channelId + "的客户端" + crewSim + "写超时");
			} else if (event.state() == IdleState.ALL_IDLE) {
				log.error("通道号为" + channelId + "的客户端" + crewSim + "超时");
			}
		}
	}

}
